package controle.acesso.dao;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import utils.Constantes;
import utils.Utils;
import model.Usuario;
import controle.acesso.model.Acesso;
import controle.acesso.model.Funcionalidade;
import controle.acesso.model.Grupo;
import controle.acesso.model.UseCase;
import dao.GenericDao;

public class AcessoDao extends GenericDao {

	private int numerodecampos = 2;
		
		public AcessoDao(){
			super();
		}


	public PreparedStatement adicionar(Acesso acesso) throws SQLException{
			
			String sql = "insert into acesso(idgrupo,idusecase) values (?,?)";
			this.setQuery(sql);
			ArrayList<Integer> indexes=new ArrayList<Integer>();
			for (int i=0;i<numerodecampos;i++)
				indexes.add(i,i+1);
			indexes.add(numerodecampos,null);
			
			PreparedStatement stmt = this.loadModelToPreparedStatement(acesso,indexes);
			
			stmt.execute();	
			this.setQuery(stmt.toString());

			stmt.close();
			
			con.close();
			return stmt;
			
		}	

	public PreparedStatement desativar(Acesso acesso) throws SQLException{
		
		String sql = "update acesso set ativo = 'N' where idacesso = ?";
		this.setQuery(sql);
		ArrayList<Integer> indexes=new ArrayList<Integer>();
		for (int i=0;i<numerodecampos;i++)
			indexes.add(i,null);
		indexes.add(numerodecampos,1);
		PreparedStatement stmt = this.loadModelToPreparedStatement(acesso, indexes);
		
		stmt.execute();
		this.setQuery(stmt.toString());

		stmt.close();
		
		con.close();
		return stmt;
		
		

	}

	public PreparedStatement ativar(Acesso acesso) throws SQLException{
		
		String sql = "update acesso set ativo = 'S' where idacesso = ?";
		this.setQuery(sql);
		ArrayList<Integer> indexes=new ArrayList<Integer>();
		for (int i=0;i<numerodecampos;i++)
			indexes.add(i,null);
		indexes.add(numerodecampos,1);
		PreparedStatement stmt = this.loadModelToPreparedStatement(acesso, indexes);
		
		stmt.execute();
		this.setQuery(stmt.toString());

		stmt.close();
		
		con.close();
		return stmt;
		
		

	}


		public PreparedStatement apagar(Acesso acesso) throws SQLException{
		String sql = "delete from acesso where idacesso = ?";
		this.setQuery(sql);
		
		ArrayList<Integer> indexes=new ArrayList<Integer>();
		for (int i=0;i<numerodecampos;i++)
			indexes.add(i,null);
		indexes.add(numerodecampos,1);
		
		PreparedStatement stmt = this.loadModelToPreparedStatement(acesso, indexes);
		
		stmt.execute();
		this.setQuery(stmt.toString());

		stmt.close();
		
		con.close();
		return stmt;
		
		

	}

	public PreparedStatement alterar(Acesso acesso) throws SQLException{
		
		String sql = "update acesso set idgrupo =?,idusecase = ?" +
				" where idacesso = ? and ativo = 'S'";
		this.setQuery(sql);
		ArrayList<Integer> indexes=new ArrayList<Integer>();
		for (int i=0;i<=numerodecampos;i++)
			indexes.add(i,i+1);
		
		PreparedStatement stmt =this.loadModelToPreparedStatement(acesso,indexes); 
		
		stmt.execute();
		
		this.setQuery(stmt.toString());

		stmt.close();
		
		con.close();
		return stmt;
		
	}

	public Integer countGetAcessos(Acesso acessoBusca) throws SQLException{
		if (acessoBusca==null) return null;
		String sql = "select count(*) as count from acesso where 1=1";		
		this.setQuery(sql);
		this.addAtivo(acessoBusca.getAtivo().charAt(0));
		ArrayList<Integer> restrictions=this.prepareRestrictionsQuery(acessoBusca);
		
		PreparedStatement stmt =this.addRestrictions(acessoBusca, restrictions);
				
		ResultSet rs = stmt.executeQuery();
		Integer count = new Integer(0);
		
		while(rs.next()){
			if (!Utils.isBlank(rs.getInt(Constantes.COUNT)))
				count=rs.getInt(Constantes.COUNT);
		} 
		this.setQuery(stmt.toString());

		stmt.close();
		rs.close();
		con.close();
		
		return count;
	}




	public ArrayList<Acesso> getAcessos(Acesso acessoBusca, int limite, int inicio) throws SQLException{
		if (acessoBusca==null) return null;
		String sql = "select * from acesso where 1=1";		
		this.setQuery(sql);
		this.addAtivo(acessoBusca.getAtivo().charAt(0));
		ArrayList<Integer> restrictions=this.prepareRestrictionsQuery(acessoBusca);
		this.addLimit(limite,inicio);
		
		PreparedStatement stmt =this.addRestrictions(acessoBusca, restrictions);
				
		ResultSet rs = stmt.executeQuery();
		Acesso acesso = null;
		ArrayList<Acesso> acessos=new ArrayList<Acesso>();
		
		while(rs.next()){
			acesso = this.loadResultSetToModel(rs);
			acessos.add(acesso);
			
		} 
		this.setQuery(stmt.toString());

		stmt.close();
		rs.close();
		con.close();
		
		return acessos;
	}





	private PreparedStatement addRestrictions(Acesso acesso,
			ArrayList<Integer> restrictions) throws SQLException {
	PreparedStatement stmt=con.prepareStatement(this.getQuery());
		
	
		if (!Utils.isBlank(restrictions.get(0)))
			stmt.setInt(restrictions.get(0), acesso.getGrupo().getId());
		
		if (!Utils.isBlank(restrictions.get(1)))
			stmt.setInt(restrictions.get(1), acesso.getUseCase().getId());
		
		if (!Utils.isBlank(restrictions.get(2)))
			stmt.setInt(restrictions.get(2), acesso.getId());
		return stmt;
	}





	private PreparedStatement loadModelToPreparedStatement(Acesso acesso ,ArrayList<Integer> indexes) throws SQLException{
		PreparedStatement stmt=con.prepareStatement(this.getQuery());
		
		
		if (!Utils.isBlank(indexes.get(0)))
			stmt.setInt(indexes.get(0), acesso.getGrupo().getId());
		
		if (!Utils.isBlank(indexes.get(1)))
			stmt.setInt(indexes.get(1), acesso.getUseCase().getId());
		
		if (!Utils.isBlank(indexes.get(2)))
			stmt.setInt(indexes.get(2), acesso.getId());
		
		return stmt;
	}


	private Acesso loadResultSetToModel(ResultSet rs) throws SQLException {
		Acesso acesso = new Acesso();
		
		if (!Utils.isBlank(rs.getInt(Constantes.IDACESSO)))
			acesso.setId(rs.getInt(Constantes.IDACESSO));
		
		
		UseCase useCase = new UseCase();
		if (!Utils.isBlank(rs.getInt(Constantes.IDUSECASE)))
			useCase.setId(rs.getInt(Constantes.IDUSECASE));
		UseCaseDao useCaseDao = new UseCaseDao();
		acesso.setUseCase(useCaseDao.getUseCases(useCase, 0, 0).get(0));
		
		Grupo grupo = new Grupo();
		if (!Utils.isBlank(rs.getInt(Constantes.IDGRUPO)))
			grupo.setId(rs.getInt(Constantes.IDGRUPO));
		GrupoDao grupoDao = new GrupoDao();
		acesso.setGrupo(grupoDao.getGrupos(grupo, 0, 0).get(0));
		
		
		if (!Utils.isBlank(rs.getString(Constantes.ATIVO)))
			acesso.setAtivo(rs.getString(Constantes.ATIVO));
		
		return acesso;
	}





	private ArrayList<Integer> prepareRestrictionsQuery(Acesso acesso){
		ArrayList<Integer> restrictions=new ArrayList<Integer>();
		int index=0;
		String sql=this.getQuery();
		
		restrictions.add(3, null);
		if (!Utils.isBlank(acesso.getGrupo().getId())){
			sql+=" and idusecase = ?";
			index++;
			restrictions.add(3, index);
		}
		
		restrictions.add(1, null);
		if (!Utils.isBlank(acesso.getUseCase().getId())){
			sql+=" and idusecase = ?";
			index++;
			restrictions.add(1, index);
		}
		
		restrictions.add(2, null);
		if (!Utils.isBlank(acesso.getId())){
			sql+=" and idacesso = ?";
			index++;
			restrictions.add(2, index);
		}

			
		this.setQuery(sql);
		return restrictions;
	}

	public Boolean getAcesso(Usuario logado, Funcionalidade funcionalidade) throws SQLException {
		// TODO Auto-generated method stub
//		buscar se existe acesso com o Grupo do logado e com o UseCase da funcionalidade
		if ((logado==null)||(funcionalidade==null)) return false;
		String sql = "select * from acesso where 1=1";		
		this.setQuery(sql);
		this.addAtivo('S');
		
		Acesso acessoBusca = new Acesso();
		acessoBusca.setGrupo(logado.getGrupo());
		acessoBusca.setUseCase(funcionalidade.getUseCase());
		
		ArrayList<Integer> restrictions=this.prepareRestrictionsQuery(acessoBusca);
		
		PreparedStatement stmt =this.addRestrictions(acessoBusca, restrictions);
				
		ResultSet rs = stmt.executeQuery();
		Acesso acesso = null;
		ArrayList<Acesso> acessos=new ArrayList<Acesso>();
		
		while(rs.next()){
			acesso = this.loadResultSetToModel(rs);
			acessos.add(acesso);
			
		} 
		this.setQuery(stmt.toString());

		stmt.close();
		rs.close();
		con.close();
		
		return !acessos.isEmpty();
		
	}


	
	
}
